package com.hdax.dmw.order.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdax.dmw.dtos.order.TicketBuyerDto;
import com.hdax.dmw.entity.item.DmItem;
import com.hdax.dmw.entity.order.DmOrder;
import com.hdax.dmw.entity.order.DmOrderLinkUser;
import com.hdax.dmw.entity.order.TxMsg;
import com.hdax.dmw.entity.scheduler.DmSchedulerSeat;
import com.hdax.dmw.entity.user.DmLinkUser;
import com.hdax.dmw.exceptions.DmwException;
import com.hdax.dmw.exceptions.order.OrderException;
import com.hdax.dmw.order.feign.ItemFeign;
import com.hdax.dmw.order.feign.LinkUserFeign;
import com.hdax.dmw.order.feign.SchedulerFeign;
import com.hdax.dmw.order.feign.UserFeign;
import com.hdax.dmw.order.mapstruct.TicketBuyerDtoMapper;
import com.hdax.dmw.order.service.DmOrderLinkUserService;
import com.hdax.dmw.order.service.DmOrderService;
import com.hdax.dmw.order.mappers.DmOrderMapper;
import com.hdax.dmw.order.service.TxMsgService;
import com.hdax.dmw.order.vo.SubmitOrderVo;
import com.hdax.dmw.utils.Result;
import com.hdax.dmw.utils.ResultGenerator;
import com.hdax.dmw.utils.ServiceResultEnum;
import com.hdax.dmw.utils.TokenUtil;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author guoyisha
* @description 针对表【dm_order(订单表)】的数据库操作Service实现
* @createDate 2023-06-15 12:14:14
*/
@Service
public class DmOrderServiceImpl extends ServiceImpl<DmOrderMapper, DmOrder>
    implements DmOrderService{

    @Autowired
    private UserFeign userFeign;
    @Autowired
    private ItemFeign itemFeign;
    @Autowired
    private SchedulerFeign schedulerFeign;
    @Autowired
    private LinkUserFeign linkUserFeign;
    @Autowired
    private TicketBuyerDtoMapper ticketBuyerDtoMapper;
    @Autowired
    private DmOrderService orderService;
    @Autowired
    private DmOrderLinkUserService orderLinkUserService;
    @Autowired
    private TxMsgService txMsgService;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Override
    public DmOrder detail(String orderNo) {
        return getOne(new QueryWrapper<DmOrder>()
                .eq("orderNo",orderNo));
    }

    public Result<List<TicketBuyerDto>> ticketBuyers(Long userId){
        List<DmLinkUser> linkusers = userFeign.linkusers(userId);
        List<TicketBuyerDto> dtos = ticketBuyerDtoMapper.toTargetList(linkusers);
        return ResultGenerator.genSuccessResult(dtos);
    }

    /**
     * 规定所有订单异常errorCode 50XX
     * 1. 用户是否登录
     * 2. 总金额计算
     * 3. 商品检查
     * 4. 人票数量是否一致
     * 5. 演出排期和剧场
     * 6. 订单联系人
     *
     * 1. 计算总金额+?保险
     * 2. 数据库修改（订单新增，座位状态修改）
     */
    @Transactional(propagation = Propagation.REQUIRED,
            rollbackFor = {OrderException.class})
    @Override
    public Result<String> submitOrder(SubmitOrderVo vo, String token) {
        DmOrder order = new DmOrder();
        //生成订单 
        Snowflake snowflake = new Snowflake();
        String orderNo = snowflake.nextIdStr();

        Map<String, String> tokenMap = null;
        Long userId = 0L;
        Integer totalAmount = 0;//订单总金额
        try {
            tokenMap = TokenUtil.parseToken(token);
            userId = Long.parseLong(tokenMap.get("id"));
        }catch (Exception e){
            ServiceResultEnum resultEnum = ServiceResultEnum.TOKEN_EXPIRE_ERROR;
            throw new OrderException(resultEnum.getCode(),resultEnum.getResult());
        }
        Long itemId = vo.getItemId();
        DmItem item = itemFeign.detail(itemId);
        order.setItemName(item.getItemName());
        if(ObjectUtil.isNull(item)){
            ServiceResultEnum resultEnum = ServiceResultEnum.GOODS_NOT_EXIST;
            throw new OrderException(resultEnum.getCode(),resultEnum.getResult());
        }
        //1,2,3,4
        String[] linkIds = vo.getLinkIds().split(",");
        //1_1,1_2,1_3
        String[] seatPositions = vo.getSeatPositions().split(",");
        if(linkIds.length != seatPositions.length){
            ServiceResultEnum resultEnum = ServiceResultEnum.ORDER_TICKET_NUM_EROOR;
            throw new OrderException(resultEnum.getCode(),resultEnum.getResult());
        }

        //每一个要修改的座位信息
        List<DmSchedulerSeat> seats = new ArrayList<>();
        //每一个座位的票价
        Integer[] prices = new Integer[linkIds.length];
        for (int i = 0; i < seatPositions.length; i++) {
            String seatString = seatPositions[i];
            Integer x = Integer.parseInt(seatString.split("_")[0]);
            Integer y = Integer.parseInt(seatString.split("_")[1]);
            Long schedulerId = vo.getSchedulerId();
            DmSchedulerSeat seat = schedulerFeign.detail(schedulerId, x, y);
            if(seat.getOrderNo()!=null &&
                seat.getUserId()!=null && seat.getStatus()!=1){
                ServiceResultEnum resultEnum = ServiceResultEnum.ORDER_SEAT_LOCK;
                throw new OrderException(resultEnum.getCode(),resultEnum.getResult());
            }
            seat.setOrderNo(orderNo);
            seat.setUserId(userId);
            seat.setStatus(2);
            seats.add(seat);
            totalAmount+=seat.getPrice();
            prices[i] = seat.getPrice();
        }

        List<DmOrderLinkUser> orderLinkUsers = new ArrayList<>();
        for (int i = 0; i < linkIds.length; i++) {
            Long linkId = Long.parseLong(linkIds[i]);
            DmLinkUser linkUser = linkUserFeign.detail(userId, linkId);
            if(ObjectUtil.isNull(linkUser)){
                ServiceResultEnum resultEnum = ServiceResultEnum.ORDER_LINK_USER_ERROR;
                throw new OrderException(resultEnum.getCode(),resultEnum.getResult());
            }
            DmOrderLinkUser orderLinkUser = new DmOrderLinkUser();
            Integer x = Integer.parseInt(seatPositions[i].split("_")[0]);
            Integer y = Integer.parseInt(seatPositions[i].split("_")[1]);
            orderLinkUser.setOrderId(Long.parseLong(orderNo));
            orderLinkUser.setLinkUserId(linkUser.getId());
            orderLinkUser.setLinkUserName(linkUser.getName());
            orderLinkUser.setX(x);
            orderLinkUser.setY(y);
            orderLinkUser.setPrice(prices[i]);
            orderLinkUsers.add(orderLinkUser);
        }
        if (vo.getIsNeedInsurance()==1) {
            totalAmount+=20;
            order.setIsNeedInsurance(vo.getIsNeedInsurance().intValue());
            order.setInsuranceAmount(20);
        }

        //订单新增
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setScheduleId(vo.getSchedulerId());
        order.setItemId(itemId);
        order.setTotalCount(linkIds.length);
        if(vo.getIsNeedInvoice() == 1){
            order.setInvoiceHead(vo.getInvoiceHead());
            order.setInvoiceNo(vo.getInvoiceId());
        }
        order.setTotalAmount(totalAmount);
        //添加数据到本地消息表
        TxMsg txMsg = new TxMsg();
        txMsg.setId(orderNo);
        LocalDateTime now = LocalDateTime.now();
        txMsg.setAtime(now);
        txMsg.setMsg_result("0");
        txMsg.setVersion(1L);
        txMsg.setTry_count(1);
        txMsg.setBiz_type("1");//1下单 2退单

        Map<String,Object> msg = new HashMap<>();
        msg.put("orderNo",orderNo);
        msg.put("atime",now.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        msg.put("linkIds",linkIds);
        msg.put("seatPositions",seatPositions);
        msg.put("userId",userId);
        msg.put("scheduleId",vo.getSchedulerId());

        txMsg.setMsg(JSONUtil.toJsonStr(msg));

        orderService.save(order);//添加订单
        orderLinkUserService.saveBatch(orderLinkUsers);
        txMsgService.save(txMsg);//本地消息表信息
        //投递消息到mq
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(orderNo);
        rabbitTemplate.convertAndSend("dm_order_tx","tx.order.save",JSONUtil.toJsonStr(txMsg),correlationData);

        Map<String,String> result = new HashMap<>();
        result.put("orderNo",orderNo);

        return ResultGenerator.genSuccessResult(result);
    }
}




